package com.cloudfun.campusshare.device.protocol.command;

import cn.hutool.core.collection.CollectionUtil;
import com.cloudfun.campusshare.common.constant.DeviceType;
import com.cloudfun.campusshare.common.model.vo.PumpWorkVO;
import com.cloudfun.campusshare.device.protocol.constant.PumpCmdType;
import com.cloudfun.campusshare.device.protocol.response.PumpWorkInfo;
import com.cloudfun.campusshare.util.ByteUtil;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description
 * @author               wangxiyuan
 * @createDate           2021/5/19 9:42
**/
public class PumpCommandFactory {
    private static final byte[] START_FLAG = new byte[]{1};

    private static final byte[] FLAG = new byte[]{0};

    private static final byte[] TIME_SETTING = new byte[]{0,0};
    // key 添加洗衣液类型 value 时间，单位s
    public static final Map<Integer, Integer> pumpStartMap = new HashMap<>();

    static {
        // 0是不限制时间
        pumpStartMap.put(0,0);
        pumpStartMap.put(1,5);
        pumpStartMap.put(2, 10);
        pumpStartMap.put(3, 15);
        pumpStartMap.put(4, 20);
        pumpStartMap.put(5, 25);
    }

    /**
     * 向控制板下发3个液体泵工作指令 启动
     * 经实际测试，即使设置了工作时间，也是按照上一次06命令设置的工作时间来工作，不符合实际工作场景
     * @param firstWorkTime 1号泵工作时间
     * @param secondWorkTime 2号泵工作时间
     * @param thirdWorkTime 3号泵工作时间
     * @return
     */
    @Deprecated
    public static PumpFrame start(int firstWorkTime,int secondWorkTime,int thirdWorkTime){
        if(firstWorkTime < 0 || secondWorkTime < 0 || thirdWorkTime < 0){
            throw new RuntimeException("pump work time must be positive ");
        }
        // 2^15 - 1  两个字节的最大长度
        if(firstWorkTime > 65535 || secondWorkTime > 65535 || thirdWorkTime > 65535){
            throw new RuntimeException("pump work time must be less than 65535");
        }
        List<byte[]> data = new ArrayList<>();
        data.add(START_FLAG);
        data.add(ByteUtil.int2Bytes(firstWorkTime,2));
        data.add(START_FLAG);
        data.add(ByteUtil.int2Bytes(secondWorkTime,2));
        data.add(START_FLAG);
        data.add(ByteUtil.int2Bytes(thirdWorkTime,2));
        return new PumpFrame((byte)PumpCmdType.WORK.getCmdType(),ByteUtil.merge(data));
    }

    public static PumpFrame startPump(String deviceType, PumpWorkVO pumpWorkVO){
        Integer second = pumpStartMap.get(pumpWorkVO.getPumpType());
        List<PumpWorkInfo>  pumpWorkInfos = new ArrayList<>();
        // 表示使用自定义的时间设置
        if(second == 0){
            pumpWorkInfos.add(new PumpWorkInfo(pumpWorkVO.getFirstPumpWorkTime(),pumpWorkVO.getFirstPumpDelayTime()));
            if(DeviceType.PUMP_LA_2.getName().equals(deviceType)){
                pumpWorkInfos.add(new PumpWorkInfo(pumpWorkVO.getSecondPumpWorkTime(),pumpWorkVO.getSecondPumpDelayTime()));
            }else{
                pumpWorkInfos.add(new PumpWorkInfo(0,0));
            }
        }else{
            // 使用固定时间启动
            pumpWorkInfos.add(new PumpWorkInfo(second,0));
            if(DeviceType.PUMP_LA_2.getName().equals(deviceType)){
                pumpWorkInfos.add(new PumpWorkInfo(second,0));
            }else{
                pumpWorkInfos.add(new PumpWorkInfo(0,0));
            }
        }
        pumpWorkInfos.add(new PumpWorkInfo(0,0));
        return delayStart(pumpWorkInfos);
    }

    /**
     * 大概1秒钟消耗 10容量
     * 根据工作时间计算消耗了多少液体
     * @param deviceType
     * @param pumpWorkVO
     * @return
     */
    public static List<Integer> costMoney(String deviceType,PumpWorkVO pumpWorkVO) {
        Integer second = pumpStartMap.get(pumpWorkVO.getPumpType());
        List<Integer>  capacities = new ArrayList<>();
        if(second == 0){
            capacities.add(pumpWorkVO.getFirstPumpWorkTime() * 10);
            if(DeviceType.PUMP_LA_2.getName().equals(deviceType)){
                capacities.add(pumpWorkVO.getSecondPumpWorkTime() * 10);
            }else{
                capacities.add(0);
            }
        }else{
            capacities.add(second * 10);
            if(DeviceType.PUMP_LA_2.getName().equals(deviceType)){
                capacities.add(second * 10);
            }else{
                capacities.add(0);
            }
        }
        return capacities;
    }

    /**
     * 向控制板下发3个液体泵延时时间和工作时间指令
     * @param pumpWorkInfos
     * @return
     */
    public static PumpFrame delayStart(List<PumpWorkInfo> pumpWorkInfos){
        if(CollectionUtil.isNotEmpty(pumpWorkInfos) && pumpWorkInfos.size() == 3){
            List<byte[]> data = new ArrayList<>();
            for (int i = 0; i < 2; i++) {
                // 单字节允许的最大长度为 2^7-1 工作时间不允许设置为 0
                if(pumpWorkInfos.get(i).getWorkTime() < 0  || pumpWorkInfos.get(i).getWorkTime() > 256){
                    throw new RuntimeException("pump work time must be positive and less than 256");
                }
                if(pumpWorkInfos.get(i).getDelayTime() < 0  && pumpWorkInfos.get(i).getDelayTime() > 65536){
                    throw new RuntimeException("pump delay time must be positive and less than 65536");
                }
                data.add(ByteUtil.int2Bytes(pumpWorkInfos.get(i).getWorkTime(),1));
                data.add(ByteUtil.int2Bytes(pumpWorkInfos.get(i).getDelayTime(),2));
            }
            // 目前最多只用到双泵，没有用到三泵
            data.add(new byte[]{0,0,0});
            return new PumpFrame((byte)PumpCmdType.DELAY_WORK.getCmdType(),ByteUtil.merge(data));
        }
        throw new RuntimeException("pump work time settings size must be equal 3");
    }


    /**
     * 读取设备3个液体泵的状态
     * @return
     */
    public static PumpFrame queryStatus(){
        return new PumpFrame((byte) PumpCmdType.GET_STATUS.getCmdType(),FLAG);
    }

    /**
     * 读取设备3个液体泵工作时间 延迟时间
     * @return
     */
    public static PumpFrame queryWorkDealyTime(){
        return new PumpFrame((byte)PumpCmdType.GET_TIME_SETTING.getCmdType(),FLAG);
    }

    public static PumpFrame reset(){
        List<byte[]> data = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            data.add(FLAG);
            data.add(TIME_SETTING);
        }
        return new PumpFrame((byte)PumpCmdType.DELAY_WORK.getCmdType(), ByteUtil.merge(data));
    }

    public static void main(String[] args) {

//        System.out.println(reset().toString());
//        System.out.println(start(1,1,1));
        List<PumpWorkInfo> pumpWorkInfos = new ArrayList<>();
        pumpWorkInfos.add(new PumpWorkInfo(5,0));
        pumpWorkInfos.add(new PumpWorkInfo(5,0));
        pumpWorkInfos.add(new PumpWorkInfo(0,0));
        System.out.println(delayStart(pumpWorkInfos));
        //System.out.println(queryStatus());
        //System.out.println(queryWorkDealyTime());
    }
}
